/**
 * 将元数据模板转换为Protobuf定义
 * @param {Template | null} templateData 元数据模板
 * @param {Template[]} allTemplates 所有模板列表，用于处理嵌套
 * @returns {string} Protobuf定义字符串
 */
import type { Template, TemplateField } from './storage';

// 类型映射表
const typeMap: Record<string, string> = {
  string: 'string',
  number: 'int32',
  boolean: 'bool',
  object: 'google.protobuf.Struct',
  array: 'repeated string'
};

/**
 * 转换为帕斯卡命名法（首字母大写）
 * @param {string} str 输入字符串
 * @returns {string} 转换后的字符串
 */
const toPascalCase = (str: string): string => {
  if (!str) return '';
  return str
    .replace(/\s+/g, '_')
    .split('_')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join('');
};

/**
 * 转换为驼峰命名法（首字母小写）
 * @param {string} str 输入字符串
 * @returns {string} 转换后的字符串
 */
const toCamelCase = (str: string): string => {
  if (!str) return '';
  const pascal = toPascalCase(str);
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
};

export const generateProto = (templateData: Template | null, allTemplates: Template[]): string => {
  if (!templateData || !templateData.name) {
    return '// 请输入模板名称并添加字段以生成Protobuf定义';
  }
  
  // 构建Protobuf内容
  const lines: string[] = [];
  lines.push('syntax = "proto3";');
  lines.push('');
  
  // 添加必要的导入
  if (templateData.fields.some(f => f.type === 'object')) {
    lines.push('import "google/protobuf/struct.proto";');
    lines.push('');
  }
  
  // 处理嵌套模板的导入（去重，避免同一个模板被嵌套多次时重复处理）
  const nestedTemplateIds = Array.from(new Set(
    templateData.fields
      .filter((f): f is TemplateField & { templateId: string } => 
        f.type === 'template' && !!f.templateId && f.templateId.trim() !== ''
      )
      .map(f => f.templateId)
  ));
  
  // 递归获取所有依赖的模板
  const getAllDependencies = (ids: string[], all: Template[]): string[] => {
    const deps = [...ids];
    ids.forEach(id => {
      const tpl = all.find(t => t.id === id);
      if (tpl?.fields) {
        const childIds = tpl.fields
          .filter((f): f is TemplateField & { templateId: string } => 
            f.type === 'template' && !!f.templateId && f.templateId.trim() !== ''
          )
          .map(f => f.templateId);
        childIds.forEach(childId => {
          if (!deps.includes(childId)) {
            deps.push(childId);
            getAllDependencies([childId], all).forEach(c => {
              if (!deps.includes(c)) deps.push(c);
            });
          }
        });
      }
    });
    return deps;
  };
  
  const allDependencies = getAllDependencies(nestedTemplateIds, allTemplates);
  
  // 生成依赖的模板定义
  allDependencies.forEach(id => {
    const tpl = allTemplates.find(t => t.id === id);
    if (tpl) {
      lines.push(`// 嵌套模板: ${tpl.name}`);
      lines.push(`message ${toPascalCase(tpl.name)} {`);
      tpl.fields
        .filter(field => field.name)
        .forEach((field, index) => {
          let protoType: string;
          if (field.type === 'template' && field.templateId && field.templateId.trim() !== '') {
            const nestedTpl = allTemplates.find(t => t.id === field.templateId);
            protoType = nestedTpl ? toPascalCase(nestedTpl.name) : 'string';
          } else {
            protoType = typeMap[field.type] || 'string';
          }
          const fieldName = toCamelCase(field.name);
          lines.push(`  ${protoType} ${fieldName} = ${index + 1};`);
        });
      lines.push('}');
      lines.push('');
    }
  });
  
  // 生成当前模板定义
  lines.push(`// ${templateData.description || '无描述'}`);
  lines.push(`message ${toPascalCase(templateData.name)} {`);
  
  templateData.fields
    .filter(field => field.name)
    .forEach((field, index) => {
      let protoType: string;
      // 处理嵌套模板类型
      if (field.type === 'template' && field.templateId && field.templateId.trim() !== '') {
        const nestedTpl = allTemplates.find(t => t.id === field.templateId);
        protoType = nestedTpl ? toPascalCase(nestedTpl.name) : 'string';
      } else {
        protoType = typeMap[field.type] || 'string';
      }
      const fieldName = toCamelCase(field.name);
      lines.push(`  ${protoType} ${fieldName} = ${index + 1};`);
    });
  
  lines.push('}');
  
  return lines.join('\n');
};

